package table

import (
	"context"
	"errors"
	"fmt"
	form "pd/server/app/pd/form/user"
	model "pd/server/app/pd/model/user"
	"pd/server/com"
	"pd/server/com/db"
	"time"

	sqlBuild "github.com/xiaohei16h/sql-build"

	"xorm.io/builder"
)

type UserTable struct {
}

func GetUserMerchantId(ctx context.Context, userId int64) (merchantId int64, err error) {
	conn, err := db.GetPdMasterConn()
	if err != nil {
		return
	}
	user := new(model.UserModel)
	q := conn.Conn.NewSession().Context(ctx)
	exist, err := q.Where("id = ?", userId).Select("merchant_id").Get(user)
	if err != nil {
		return
	}
	if !exist {
		err = errors.New("用户ID不存在")
		return
	}
	merchantId = user.MerchantId
	return
}

func (this *UserTable) Login(ctx context.Context, frm *form.LoginForm) (user *model.UserModel, err error) {
	conn, err := db.GetPdMasterConn()
	if err != nil {
		return
	}
	user = new(model.UserModel)
	q := conn.Conn.NewSession().Context(ctx)
	exist, err := q.Where("user_name = ?", frm.UserName).
		Select("*").
		Get(user)
	if err != nil {
		return
	}
	if !exist {
		err = fmt.Errorf("用户名不存在")
		return
	}
	if user.Password != frm.Password {
		err = errors.New("密码错误")
		return
	}

	return
}

func (this *UserTable) GetUserPowerList(ctx context.Context, userId int64) (menuList []*model.PowerNode, err error) {
	conn, err := db.GetPdMasterConn()
	if err != nil {
		return
	}
	q := conn.Conn.NewSession().Context(ctx)
	var roleIds []int64
	if q.Table(&model.RoleUserMapModel{}).Where("user_id = ?", userId).Select("role_id").Find(&roleIds); err != nil {
		return
	}

	var tmpList []*model.PowerNode
	bu := builder.Select("power_id").From((&model.RolePowerMapModel{}).TableName()).
		Where(builder.In("role_id", roleIds))
	if err = q.Table(&model.PowerModel{}).In("id", bu).
		Select("*").
		Find(&tmpList); err != nil {
		return
	}
	set := make(map[int64]*model.PowerNode, len(tmpList))
	for _, node := range tmpList {
		set[node.Id] = node
		if node.ParentId == 0 {
			menuList = append(menuList, node)
		}
	}

	for _, node := range tmpList {
		if node.ParentId != 0 {
			if tmp := set[node.ParentId]; tmp != nil {
				tmp.Children = append(tmp.Children, node)
			}
		}
	}

	return
}

func (this *UserTable) SetPower(ctx context.Context, frm *model.PowerNode) (err error) {
	conn, err := db.GetPdMasterConn()
	if err != nil {
		return
	}
	sess := conn.Conn.NewSession().Context(ctx)
	if err = sess.Begin(); err != nil {
		return
	}
	defer func() {
		if err == nil {
			err = sess.Commit()
		}
		if err != nil {
			sess.Rollback()
		}
	}()

	now := time.Now()
	var add func(*model.PowerNode) error
	add = func(node *model.PowerNode) error {
		p := new(model.PowerModel)
		com.ObjectToObject(node, p)
		p.ParentId = node.ParentId
		p.CreateTime = now
		sql, err2 := sqlBuild.Insert((&model.PowerModel{}).TableName()).
			Values([]*model.PowerModel{p}).
			OrUpdate().
			NoOnDuplicateKeyUpdateOption("id", "create_time").
			String()
		if err2 != nil {
			return err2
		}
		if _, err2 = sess.Exec(sql); err2 != nil {
			return err2
		}
		parentId := int64(0)
		if len(node.Children) > 0 {
			if _, err2 = sess.Table(&model.PowerModel{}).
				Where("code = ?", p.Code).
				Select("id").
				Get(&parentId); err2 != nil {
				return err2
			}
		}

		for _, child := range node.Children {
			child.ParentId = parentId
			if err2 = add(child); err2 != nil {
				return err2
			}
		}
		return nil
	}

	if frm.Code != "" {
		if err = add(frm); err != nil {
			return
		}
	} else {
		for _, child := range frm.Children {
			if err = add(child); err != nil {
				return
			}
		}
	}

	// 绑定店长角色(暂时写死)
	_, err = sess.Exec("insert into role_power_map (select 0, 1, id, now() from power where id not in (select power_id from role_power_map where role_id = 1));")

	return
}

func (this *UserTable) EmployeeList(ctx context.Context, frm *form.EmployeeListForm) (userList []*model.UserModel, total int64, err error) {
	conn, err := db.GetPdMasterConn()
	if err != nil {
		return
	}
	q := conn.Conn.NewSession().Context(ctx)
	q.Where("merchant_id = ?", frm.MerchantId)

	if frm.Keyword != "" {
		tmp := fmt.Sprintf("%%%s%%", frm.Keyword)
		q.Where("real_name like ? or phone_number like ?", tmp, tmp)
	}
	if frm.UserName != "" {
		q.Where("user_name like ?", fmt.Sprintf("%%%s%%", frm.UserName))
	}
	if frm.Status != "" {
		q.Where("status = ?", frm.Status)
	}
	if frm.Current > 0 {
		q.Limit(frm.Size, (frm.Current-1)*frm.Size)
	} else {
		q.Limit(1000)
	}

	q.Desc("id")
	total, err = q.Select("*").FindAndCount(&userList)
	for _, user := range userList {
		user.Password = ""
	}
	return
}

func (this *UserTable) AddEmployee(ctx context.Context, frm *form.AddEmployeeForm) (err error) {
	conn, err := db.GetPdMasterConn()
	if err != nil {
		return
	}
	sess := conn.Conn.NewSession().Context(ctx)
	if err = sess.Begin(); err != nil {
		return
	}
	defer func() {
		if err == nil {
			err = sess.Commit()
		}
		if err != nil {
			sess.Rollback()
		}
	}()

	if _, err = sess.InsertOne(frm.UserModel); err != nil {
		return
	}

	mp := &model.RoleUserMapModel{
		RoleId:     frm.RoleId,
		UserId:     frm.Id,
		CreateTime: time.Now(),
	}
	if _, err = sess.InsertOne(mp); err != nil {
		return
	}
	return
}

func (this *UserTable) ModifyPassword(ctx context.Context, frm *form.ModifyPasswordForm) (err error) {
	conn, err := db.GetPdMasterConn()
	if err != nil {
		return
	}
	q := conn.Conn.NewSession().Context(ctx)
	affected, err := q.Where("id = ? and password = ?", frm.OperatorId, frm.OldPassword).
		Cols("password").
		Update(&model.UserModel{Password: frm.NewPassword})
	if err != nil {
		return
	}
	if affected != 1 {
		err = fmt.Errorf("修改失败")
	}
	return
}

func (this *UserTable) UpdateEmployee(ctx context.Context, frm *form.AddEmployeeForm) (err error) {
	conn, err := db.GetPdMasterConn()
	if err != nil {
		return
	}
	q := conn.Conn.NewSession().Context(ctx)
	frm.LastUpdateTime = time.Now()
	affected, err := q.Where("id = ? and pa_user_id = ?", frm.Id, frm.PaUserId).
		Cols("real_name", "phone_number", "password", "last_update_time").
		Update(frm.UserModel)
	if err != nil {
		return
	}
	if affected != 1 {
		err = fmt.Errorf("更新失败")
	}
	return
}

func (this *UserTable) RemoveEmployee(ctx context.Context, frm *form.AddEmployeeForm) (err error) {
	conn, err := db.GetPdMasterConn()
	if err != nil {
		return
	}
	q := conn.Conn.NewSession().Context(ctx)
	affected, err := q.Where("id = ? and pa_user_id = ?", frm.Id, frm.PaUserId).
		Delete(&model.UserModel{})
	if err != nil {
		return
	}
	if affected != 1 {
		err = fmt.Errorf("删除失败")
	}
	return
}

func (this *UserTable) GetUserBatch(ctx context.Context, userIds []int64) (users map[int64]*model.UserModel, err error) {
	conn, err := db.GetPdMasterConn()
	if err != nil {
		return
	}
	q := conn.Conn.NewSession().Context(ctx)
	var userList []*model.UserModel
	if err = q.In("id", userIds).Select("*").Find(&userList); err != nil {
		return
	}
	users = make(map[int64]*model.UserModel)
	for _, user := range userList {
		users[user.Id] = user
	}
	return
}
